package com.mvm.store.domain.dao.base;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class AbstractHibernateDAOImpl<T extends Serializable, KeyType extends Serializable>
		extends HibernateDaoSupport implements AbstractDAO<T, KeyType> {

	private Class<T> domainClass = null;

	
	/**
	 * Method to return the class of the domain object
	 */
	@SuppressWarnings("unchecked")
	protected Class<T> getDomainClass() {
	    if (domainClass == null) {
	    	ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
	        domainClass = (Class<T>) thisType.getActualTypeArguments()[0];
	    }
	    return domainClass;
	}


	@SuppressWarnings("unchecked")
	public T load(KeyType id) {
		return (T) getHibernateTemplate().load(getDomainClass(), id);
	}

	public void update(T t) {
		getHibernateTemplate().update(t);
	}

	public void save(T t) {
		getHibernateTemplate().save(t);
	}

	public void delete(T t) {
		getHibernateTemplate().delete(t);
	}

	@SuppressWarnings("unchecked")
	public List<T> list() {
		return (getHibernateTemplate().find("from "
				+ getDomainClass().getName() + " x"));
	}

	public void deleteById(KeyType id) {
		Object obj = load(id);
		getHibernateTemplate().delete(obj);
	}

	public void deleteAll() {
		getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				String hqlDelete = "delete " + getDomainClass().getName();
				session.createQuery(hqlDelete).executeUpdate();
				return null;
			}

		});
	}

	@SuppressWarnings("unchecked")
	public int count() {
		List list = getHibernateTemplate().find(
				"select count(*) from " + getDomainClass().getName() + " x");
		Integer count = (Integer) list.get(0);
		return count.intValue();
	}

}
